#include "dominion.h"
#include <stdio.h>
#include "rngs.h"
#include <stdlib.h>
#include "math.h"
#include "dominion_helpers.h"
#include "testutilities.h"
#include <assert.h>


void printGameState(struct gameState *g, FILE *fp){
	/*number of players
	  int numPlayers; //number of players
  int supplyCount[treasure_map+1];  //this is the amount of a specific type of card given a specific number.
  int embargoTokens[treasure_map+1];
  int outpostPlayed;
  int outpostTurn;
  int whoseTurn;
  int phase;
  int numActions;  Starts at 1 each turn 
  int coins;  Use as you see fit! 
  int numBuys; Starts at 1 each turn 
  int hand[MAX_PLAYERS][MAX_HAND];
  int handCount[MAX_PLAYERS];
  int deck[MAX_PLAYERS][MAX_DECK];
  int deckCount[MAX_PLAYERS];
  int discard[MAX_PLAYERS][MAX_DECK];
  int discardCount[MAX_PLAYERS];
  int playedCards[MAX_DECK];
  int playedCardCount;
	all kingdom cards and the number in each stack
	*/
	int i;
	int j;
	fprintf(fp, "****GAME STATE****\n");
	fprintf(fp, "Number of Players: %d\n", g->numPlayers);
	fprintf(fp, "Whose turn: %d", g->whoseTurn);
	fprintf(fp, "Supply Count:\n");
	for(i=0; i<treasure_map + 1; i++){
		fprintf(fp, "	Card: %d Amount: %d\n", i, g->supplyCount[i]);
	}
	fprintf(fp, "Embargo Tokens\n");
	for(i=0; i<treasure_map +1; i++){
		fprintf(fp, "	Card: %d Tokens: %d\n", i, g->embargoTokens[i]);
	}
	fprintf(fp, "Outpost Played Status: %d\n", g->outpostPlayed);
	fprintf(fp, "Outpost Turn: %d\n", g->outpostTurn);
	fprintf(fp, "Phase: %d\n", g->phase);
	fprintf(fp, "Actions: %d\n", g->numActions);
	fprintf(fp, "Coins: %d\n", g->coins);
	fprintf(fp, "Buys: %d\n", g->numBuys);
	fprintf(fp, "HANDS\n");
	for(i=0; i< g->numPlayers; i++){
		fprintf(fp, "	Player %d Hand Count: %d\n    Hand: ", i, g->handCount[i]);
		for(j=0; j < g->handCount[i]; j++){
			fprintf(fp, "%d, ", g->hand[i][j]);
		//	if(j % 10 == 0 && j != 0){
		//		fprintf(fp, "\n          ");
		//	}
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "DECKS\n");
	for(i=0; i< g->numPlayers; i++){
		fprintf(fp, "	Player %d Deck Count: %d\n    Deck: ", i, g->deckCount[i]);
		for(j=0; j < g->deckCount[i]; j++){
			fprintf(fp, "%d, ", g->deck[i][j]);
		//	if(j % 10 == 0 && j != 0){
		//		fprintf(fp, "\n          ");
		//	}
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "DISCARDS\n");
	for(i=0; i< g->numPlayers; i++){
		fprintf(fp, "	Player %d Discard Count: %d\n    Discard: ", i, g->discardCount[i]);
		for(j=0; j < g->discardCount[i]; j++){
			fprintf(fp, "%d, ", g->discard[i][j]);
		//	if(j % 10 == 0 && j != 0){
		//		fprintf(fp, "\n          ");
		//	}
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "Played Count: %d\n    Played Cards: ", g->playedCardCount);
	for(i=0; i < g->playedCardCount; i++){
		fprintf(fp, "%d, ", g->playedCards[i]);
	//	if(i % 10 == 0 && i != 0){
	//		fprintf(fp, "\n     ");
	//	}
	}
	fprintf(fp, "\n");
}


//sets the seed in a stream
void prepRandom(int strm, int seed){
  SelectStream(strm);
  PutSeed((long)seed);
}

//returns a random number between min and max, inclusive
//prepRandom must be called one time before using this
int getRandomNumber(int min, int max){
	int number = floor(Random() * ((max-min)+1));
	number += min;
	if(number > max){
		number = max;
	}
	return number;

}

//prints player's hand to the console
void printHand(struct gameState *g, int player){
	int i;
	printf("Player %d's hand:\n", player);
	int count = g->handCount[player];
	for(i=0; i< count; i++){
		printf("%d, ", g->hand[player][i]);
	}
	printf("\n");
}
void printDeck(struct gameState *g, int player){
	int i;
	printf("Player %d's deck:\n", player);
	int count = g->deckCount[player];
	for(i=0; i< count; i++){
		printf("%d, ", g->deck[player][i]);
	}
	printf("\n");
}

void printDiscard(struct gameState *g, int player){
	int i;
	printf("Player %d's discard:\n", player);
	int count = g->discardCount[player];
	for(i=0; i< count; i++){
		printf("%d, ", g->discard[player][i]);
	}
	printf("\n");
}

void printPlayed(struct gameState *g){
	int i;
	printf("Player %d's played stack:\n", g->whoseTurn);
	int count = g->playedCardCount;
	for(i=0; i< count; i++){
		printf("%d, ", g->playedCards[i]);
	}
	printf("\n");
}


//returns the position of the card being searched
// or -1 if not found
int searchHand(struct gameState *g, int player, int card){
	int i;
	for(i=0; i<g->handCount[player]; i++){
		if(g->hand[player][i] == card){
			return i;
		}
	}
	return -1;
}

//returns a count of how many of a specific card are in a hand
int howManyInHand(struct gameState*g, int player, int card){
	int i;
	int count = 0;
	for(i=0; i<g->handCount[player]; i++){
		if(g->hand[player][i] == card){
			count++;
		}
	}
	return count;
}

//counts how many of a specific card are in a set, returns the number
//set: hand = 1, deck = 2, discard = 3, playedCards = 4, all = 5
//excludes playedCards if not asking for current player
int countCardsInSet(struct gameState *g, int player, int card, int set){
	int i;
	int count = 0;
	if(set == 1 || set == 5){//counts specific card in the hand
		for(i=0; i<g->handCount[player]; i++){
			if(g->hand[player][i] == card){
				count ++;
			}
		}
	}
	if(set == 2 || set == 5){//counts specific card in the deck
		for(i=0; i<g->deckCount[player]; i++){
			if(g->deck[player][i] == card){
				count ++;
			}
		}
	}
	if(set == 3 || set == 5){//counts specific card in the discard
		for(i=0; i<g->discardCount[player]; i++){
			if(g->discard[player][i] == card){
				count ++;
			}
		}
	}
	if(g->whoseTurn == player){
		if(set == 4 || set == 5){//counts specific card in the hand
			for(i=0; i<g->playedCardCount; i++){
				if(g->playedCards[i] == card){
					count ++;
				}
			}
		}
	}
	return count;
}

//returns an ARRAY of totals of all cards in deck, discard and hand
//from a specific player
//ignores playedHand if not current player
//which: 1 = hand, 2 = deck, 3 = discard, 4 = playedCards, 5 = all
int *countAllOtherCards(struct gameState *g, int which, int player){
	assert(which > 0 && which <= 5);
	assert(player >= 0 && player < 5);
	int deckCount = g->deckCount[player];
	int discardCount = g->discardCount[player];
	int handCount = g->handCount[player];
	int playedCardCount = g->playedCardCount;

	int* allCards = malloc(sizeof(int) * TOTALSUPPLYCOUNT);

	int i, j;
	for(i=0; i<TOTALSUPPLYCOUNT; i++){
		allCards[i] = 0;  //just to be sure
	}
	for (i=0; i<TOTALSUPPLYCOUNT; i++){
		if(which == 1 || which == 5){
			for(j=0; j < handCount; j++){
				if (g->hand[player][j] == i){
					allCards[i]++;
				}
			}
		}
		if(which == 2 || which == 5){
			for(j=0; j < deckCount; j++){
				if (g->deck[player][j] == i){
					allCards[i]++;
				}
			}
		}
		if(which == 3 || which == 5){
			for(j = 0; j< discardCount; j++){
				if(g->discard[player][j] == i){
					allCards[i]++;
				}
			}
		}
		if(g->whoseTurn == player){
			if(which == 4 || which == 5){
				for(j = 0; j< playedCardCount; j++){
					if(g->playedCards[j] == i){
						allCards[i]++;
					}
				}
			}
		}
	}
	return allCards;
}

//compares number of cards from two sets
//returns 1 if equal, 0 if not
int compareSupplySet(int *set1, int *set2){
	int i;
	int pass = 1;
	for(i=0; i<TOTALSUPPLYCOUNT; i++){
		if(set1[i] != set2[i]){
			//printf("card count for %d: set1: %d set2: %d\n", i, set1[i],set2[i]);
			//return 0;
			pass = 0;
		}
	}
	if (pass == 1)
		return 1;
	else
		return 0;
}

void randomizeSupply(struct gameState *g){
	int i;
	for(i=0; i < TOTALSUPPLYCOUNT; i++){
		g->supplyCount[i] = getRandomNumber(0, 40);
	}
}

void randomizeHands(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->handCount[i] = getRandomNumber(0, 20);
		for(j = 0; j < g->handCount[i]; j++){
			g->hand[i][j] = getRandomNumber(0, TOTALSUPPLYCOUNT -1);
			if(g->hand[i][j] == TOTALSUPPLYCOUNT) g->hand[i][j] = 26;
		}

	}
}

void randomizeDecks(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->deckCount[i] = getRandomNumber(0, 50);
		for(j = 0; j < g->deckCount[i]; j++){
			g->deck[i][j] = getRandomNumber(0, TOTALSUPPLYCOUNT-1);
			if(g->deck[i][j] == TOTALSUPPLYCOUNT) g->deck[i][j] = 26;
		}

	}
	
}

void randomizeDiscard(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->discardCount[i] = getRandomNumber(0, 50);
		for(j = 0; j < g->discardCount[i]; j++){
			g->discard[i][j] = getRandomNumber(0, TOTALSUPPLYCOUNT-1);
			if(g->discard[i][j] == TOTALSUPPLYCOUNT) g->discard[i][j] = 26;
		}

	}
	
}
void randomizeTurn(struct gameState *g){
	g->whoseTurn = getRandomNumber(0, (g->numPlayers -1));
}

void randomizeOutpost(struct gameState *g){
	int random = getRandomNumber(0,20);
	if(random == 20){
		g->outpostPlayed = 1;
	}
	else{
		g->outpostPlayed = 0;
	}
}

//puts cards int the played hand, but does not check to see if they are valid choices
void randomizePlayed(struct gameState *g){
	g->playedCardCount = getRandomNumber(0, 10);
	int i;
	for(i=0; i < g->playedCardCount; i++){
		int card = getRandomNumber(7,26);
		g->playedCards[i] = card;
	}
}

//calls other functions to randomize the number of players, supply, decks, 
//discards, hands, turns, coins, numActions, and numBuys
//returns 0 upon completion
void makeRandomGameState(struct gameState *g){
//	printf("Randomizing Game\n");
	g->numPlayers = getRandomNumber(2, 5);
	if(g->numPlayers == 5) g->numPlayers = 4;
	randomizeSupply(g);
	randomizeDecks(g);
	randomizeDiscard(g);
	randomizeHands(g);
	randomizeTurn(g);
	randomizeOutpost(g);
	randomizePlayed(g);
	g->coins = getRandomNumber(0, 20);
	g->numActions = getRandomNumber(0, 5);
	g->numBuys = getRandomNumber(0, 3);
//	printf("Game Randomized\n");

}

//returns a count of the coins represented in the current player's hand
//this does NOT include any bonuses that have accumulated
int coinsInHand(struct gameState *g){
	int coins;
	int i;
	for(i = 0; i < g->handCount[g->whoseTurn]; i++){
		if(g->hand[g->whoseTurn][i] == copper){
			coins ++;
		}
		if(g->hand[g->whoseTurn][i] == silver){
			coins = coins + 2;
		}
		if(g->hand[g->whoseTurn][i]== gold){
			coins = coins + 3;
		}
	}
	return coins;
}

//copies an array
//returns the copy of the array
int copySet(int *array, int *newArray, int length){
	if(array == NULL){
		printf("nothing to copy");
		return -1;
	}

	int i;
	for(i=0; i<length; i++){
		newArray[i] = array[i];
	}

	return 1;

}

//returns -1 if lengths are different, 0 if values are different
//1 if all values are the same
int compareSet(int *array1, int *array2, int length1, int length2){
	if(length1 != length2){
		printf("lengths not the same\n");
		return -1;
	}
	int i;
	for(i=0; i<length1; i++){
		if(array1[i] != array2[i]){
			return 0;
		}
	}
	return 1;
}


